package com.example.nio.component;

import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.nio.commons.*;
import com.example.nio.config.FlowNumHandler;
import com.example.nio.config.MessageSendService;
import com.example.nio.config.RedisConfig;
import com.example.nio.dao.StatisReportMapper;
import com.example.nio.service.AgentService;
import com.example.nio.service.MessageDisposeService;
import com.example.nio.utils.*;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import java.util.*;

@Component
@ChannelHandler.Sharable
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

	@Autowired
	private AgentService agentService;
	@Autowired
	private MessageSendService messageSendService;
	@Autowired
	private MessageDisposeService messageDisposeService;

	@Autowired
	private StatisReportMapper statisReportMapper;

	@Autowired
	private RedisConfig redisConfig;

	Logger logger = LoggerFactory.getLogger(ChatHandler.class);

	private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

	// 建立链接时 会触发的事件进入
	@Override
	public void handlerAdded(ChannelHandlerContext ctx) {
//		for (Channel channel : channels) {
//			channel.writeAndFlush(new TextWebSocketFrame(ctx.channel().remoteAddress() + "进入聊天室"));
//		}
		System.out.println("客服建立了连接");
		channels.add(ctx.channel());
	}

	// 客服退出
	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		Agent agent = AssignedUtil.getAgentByChannel(ctx.channel());
		System.out.println("websocket close");
		new Timer("close", true).schedule(new TimerTask() {
			@Override
			public void run() {
				System.out.println("执行websocket close方法的定时器");
				if (redisConfig.setNx(agent.getAgent()+"onLine","1",2000)){
					//并计算保存聊天时长   记录通话记录
					List<String> toUserList = AgentUserUtil.getUserByAgent(agent);
					for (String s : toUserList) {
						// 提醒用户 客服下线原因 导致的断线
						AgentUserUtil.deleteUser(s);
						StatisReport statisReport = StatisReportUtil.getStatisReportByUserId(s);
						statisReport.setCallEnd(new Date());
						Integer callAllTime = statisReport.getMillisecBetweenDate(statisReport.getCallStart(),
								statisReport.getCallEnd());
						statisReport.setCallAllTime(callAllTime).setCloseReason(1);
						// 添加进数据库
						statisReportMapper.add(statisReport);

						// 最后发消息的人如果是用户的话 代表消息未被回复
						if (statisReport.getIsLast()){
							statisReport.setIsRespond(1);
						}
						statisReportMapper.addAgentRespond(statisReport);
						StatisReportUtil.closeStatisReport(s);
					}
					// 客服退出就删除所有已接入的用户
					AgentUserUtil.deleteAgent(agent);
					// 在客服列表中删除对应的客服
					AssignedUtil.deleteAgent(agent);
					agentListUpdate(agent);
					logger.info("客服: "+ agent.getAgent() +"断开了连接" + "的websocket断开");
				}
			}
		}, 5000);
//		//并计算保存聊天时长   记录通话记录
//		List<String> toUserList = AgentUserUtil.getUserByAgent(agent);
//
// 		for (String s : toUserList) {
//			// 提醒用户 客服下线原因 导致的断线
//			AgentUserUtil.deleteUser(s);
//			StatisReport statisReport = StatisReportUtil.getStatisReportByUserId(s);
//			statisReport.setCallEnd(new Date());
//			Integer callAllTime = statisReport.getMillisecBetweenDate(statisReport.getCallStart(),
//					statisReport.getCallEnd());
//			statisReport.setCallAllTime(callAllTime).setCloseReason(1);
//			// 添加进数据库
//			statisReportMapper.add(statisReport);
//
//			// 最后发消息的人如果是用户的话 代表消息未被回复
//			if (statisReport.getIsLast()){
//				statisReport.setIsRespond(1);
//			}
//			statisReportMapper.addAgentRespond(statisReport);
//			StatisReportUtil.closeStatisReport(s);
//		}
//		// 客服退出就删除所有已接入的用户
//		AgentUserUtil.deleteAgent(agent);
//		// 在客服列表中删除对应的客服
//		AssignedUtil.deleteAgent(agent);
//		agentListUpdate(agent);
//		logger.info("客服: "+ agent.getAgent() +"断开了连接" + "的websocket断开");
	}

	// 客服列表刷新  ①客服初始化 ②客服断开websocket连接
	private void agentListUpdate(Agent agent){
		ChatMessage chatMessage = new ChatMessage();
		chatMessage.setMsgType("clientRefresh");
		if (agent != null){
			BridgeUtil.toClient(chatMessage,agent);
		} else{
			List<Agent> agentList = AssignedUtil.getAgentByDepartment("1");
			// 客服上线 告诉其他已在线的客服
			if (agentList.size() > 0){
				for (Agent agent1: agentList){
					BridgeUtil.toClient(chatMessage,agent1);
				}
			}
		}
	}
	// 广播
	// 从websocket处接受到消息
	@Override
	protected void messageReceived(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
		String content = msg.text();
		Channel ichannel = ctx.channel();
		WsChange wsChange = new WsChange();
		Message message;
		// 拼接消息的对象 进行消息的发送  根据消息类型来判断操作（用户结束通话、发送消息、初始化客服）

		// 判断连接时长 多久时长之后就 断开连接

		// 增加通话记录

		Integer clientType = JSONUtil.parseObj(content).getInt("clientType");
		System.out.println("server收到消息:" + content);
		// 判断是否存在ClientType
		if (clientType != null) {
			// 判断是否初始化用户名
			switch (clientType) {
				case 1:
					Agent agent = wsChange.agentChange(content);
					// 代表客服初始化了
					redisConfig.setNx(agent.getAgent()+"onLine","1",7000);

					String agentid = agent.getAgent();
					agent.setState(1);
					//判断客服是否存在数据库
					if (agentService.getAgentByColumn(agentid) == null) {
						agentService.add(agent);
					}
					// 判断客服是否存在map中
					if (AssignedUtil.getGroupByAgentId(agentid) != null) {
						Agent ag = AssignedUtil.getAgentByAgentId(agentid);
						message = new Message();
						List<String> toUserList = AgentUserUtil.getUserByAgent(ag);
						for (String s : toUserList) {
							message.setTo(s).setContent("非常抱歉，由于业务繁忙导致连接异常，后续咨询请重新输入'客服'，感谢您的支持与信任！").setFrom(ag.getDepartment()).setShowdate(new Date());
							// 发送消息给用户
						}
					}
//					if (AssignedUtil.getAgentByAgentId(agentid)!= null){
//						AssignedUtil.deleteAgent(agent);
//					}
//					agent.setChannel(ichannel);
//					AssignedUtil.addAgent(agent);
					agent.setChannel(ichannel);
					if (AssignedUtil.getAgentByAgentId(agentid)!= null){
//						AssignedUtil.deleteAgent(agent);
						AssignedUtil.resetAgent(agent);
						AgentUserUtil.updateAgentChannel(agent);
					} else{
						AssignedUtil.addAgent(agent);
					}
					System.out.println(AssignedUtil.assigned.toString());
					System.out.println(AgentUserUtil.getUserByAgent(agent));
					logger.info("客服:" + agentid);
					agentListUpdate(null);
					break;
				case 2:
					JSONObject jsonObject = JSONUtil.parseObj(content);
					String state = jsonObject.getStr("state");
					ChatMessage chatMessage = JSONUtil.toBean(state,ChatMessage.class);
					Agent agent1 = AgentUserUtil.getAgentByUser(chatMessage.getToUser());
					logger.info(chatMessage.getToUser() + "与" + agent1.getAgent() + "对话");
					chatMessage.setSystemTime(System.currentTimeMillis());
//					flowNumHandler.put(UUID.randomUUID().toString(),chatMessage);
 					messageSendService.sendMessage(chatMessage);

				    // 发送方是客服 接收方是
					StatisReport statisReport = StatisReportUtil.getStatisReportByUserId(chatMessage.getToUser());
					// true 代表上一条消息是用户发的
					if (statisReport != null && statisReport.getIsLast()){
						statisReport.setReplyTime(new Date());
						statisReport.setIsRespond(0);
						statisReport.setRespondTime(statisReport.getMillisecBetweenDate(statisReport.getReceiveTime(),statisReport.getReplyTime()));
						statisReportMapper.addAgentRespond(statisReport);
						statisReport.setIsLast(false);
					}
					Timer timer = new Timer(chatMessage.getToUser(),true);
					// 客服最后发送消息  true
					AgentUserUtil.setLastMessage(chatMessage.getToUser(),true);
					// 当用户发送信息回来之后  请求
					timer.schedule(new TimerTask() {
						@Override
						public void run() {
						// 如果最后
						if (AgentUserUtil.checkMessageLast(chatMessage.getToUser()) ) {
							System.out.println("此处设置了定时任务，客服回复消息之后，如果用户15分钟之后没有发送消息就询问是否有其他需要帮助的");
							System.out.println("当前客服连接：" + AgentUserUtil.agentUser.toString());
							chatMessage.setContent("是否还有其他可以帮到您的");
							chatMessage.setSystemTime(System.currentTimeMillis());
							messageSendService.sendMessage(chatMessage);

							Timer timer1 = new Timer(chatMessage.getToUser(), true);
							timer1.schedule(new TimerTask() {
								@Override
								public void run() {
									System.out.println("此次咨询进行最后等待五分钟");
									if (AgentUserUtil.checkMessageLast(chatMessage.getToUser()) ) {
										// 这是发给用户的
										chatMessage.setContent("此处咨询已结束");
										chatMessage.setMsgType("userLeave");
										chatMessage.setSystemTime(System.currentTimeMillis());
										messageSendService.sendMessage(chatMessage);
										System.out.println("当前客服连接：" + AgentUserUtil.agentUser.toString());
										// 把来源名称设置成当前用户  发送给客服 告诉客服 用户下线
										ChatMessage message = new ChatMessage();
										message.setMsgType("userBroken");
										message.setContent("用户" + chatMessage.getToUser() + "断开了连接");
										message.setFromUser(chatMessage.getToUser());
										message.setToUser(chatMessage.getFromUser());
										message.setMessageSource(chatMessage.getMessageSource());
										messageDisposeService.messageHandling(message);
									}
								}
								// 300
							},1000 * 5);
						}
						}
						// 900
					},1000 * 20);
					break;
				default:
					break;
			}
		}
	}
}
